package com.ecoolex.chinadutyfree.retailer.core.manager;

import java.math.BigDecimal;
import java.time.Instant;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ecoolex.chinadutyfree.retailer.core.dao.DirectMailGoodsShoppingCartDAO;
import com.ecoolex.chinadutyfree.retailer.entity.DirectMailGoods;
import com.ecoolex.chinadutyfree.retailer.entity.DirectMailGoodsProduct;
import com.ecoolex.chinadutyfree.retailer.entity.DirectMailGoodsShoppingCart;
import com.ecoolex.chinadutyfree.retailer.entity.DirectMailGoodsShoppingCart.Column;
import com.ecoolex.chinadutyfree.retailer.entity.DirectMailGoodsShoppingCartExample;
import com.ecoolex.chinadutyfree.retailer.entity.DirectMailGoodsShoppingCartExample.Criteria;
import com.ecoolex.chinadutyfree.retailer.entity.Goods;
import com.ecoolex.chinadutyfree.retailer.entity.GoodsProduct;
import com.ecoolex.chinadutyfree.retailer.enums.DirectMailGoodsProductStatus;
import com.ecoolex.chinadutyfree.retailer.enums.DirectMailGoodsShoppingCartStatus;
import com.ecoolex.chinadutyfree.retailer.enums.DirectMailGoodsStatus;
import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.pojo.Page;
import com.ecoolex.framework.common.pojo.Pagination;
import com.ecoolex.framework.common.pojo.Sorting;
import com.ecoolex.framework.common.pojo.Sortings;
import com.ecoolex.framework.common.util.BizAssert;
import com.ecoolex.framework.common.util.Check;


@Service
public class DirectMailGoodsShoppingCartManager {

    @Autowired
    private DirectMailGoodsShoppingCartDAO dao;

    @Autowired
    private DirectMailGoodsProductManager directMailProductManager;

    @Autowired
    private DirectMailGoodsManager directMailGoodsManager;

    @Autowired
    private GoodsManager goodsManager;

    @Autowired
    private GoodsProductManager goodsProductManager;

    public DirectMailGoodsShoppingCart add(Integer directMailProductId, Integer buyNumber, Integer userId, String userName, Boolean isTemporary) {
        DirectMailGoodsProduct dmProduct = directMailProductManager.getById(directMailProductId);
        BizAssert.isTrue(Check.notNull(dmProduct), ResultCode.VERIFY.build(10), "直邮产品不存在");
        BizAssert.isTrue(DirectMailGoodsProductStatus.NORMAL.equal(dmProduct.getStatus()),
            ResultCode.VERIFY.build(11),
            "直邮产品已失效");

        DirectMailGoods dmGoods = directMailGoodsManager.getById(dmProduct.getDirectMailGoodsId());
        BizAssert.isTrue(Check.notNull(dmGoods), ResultCode.VERIFY.build(20), "直邮商品不存在");
        BizAssert.isTrue(DirectMailGoodsStatus.RELEASE.equal(dmGoods.getStatus()),
            ResultCode.VERIFY.build(21),
            "直邮商品已失效");

        GoodsProduct product = goodsProductManager.getById(dmProduct.getProductId());
        BizAssert.isTrue(Check.notNull(product), ResultCode.VERIFY.build(30), "产品不存在");

        Goods goods = goodsManager.getById(dmProduct.getGoodsId());
        BizAssert.isTrue(Check.notNull(goods), ResultCode.VERIFY.build(41), "商品不存在");

        // 购物车是否临时，在用户直接点击购买时调用加入购物车接口，此字段传true
        isTemporary = Check.isNull(isTemporary) ? false
            : isTemporary;

        if (!isTemporary) {
            DirectMailGoodsShoppingCart shoppingCart
                = getByDirectMailProductIdAndNotTemporary(userId, directMailProductId);
            if (Check.notNull(shoppingCart)) {
                shoppingCart.setBuyNumber(shoppingCart.getBuyNumber() + buyNumber);
                shoppingCart.setUpdateUser(userName);
                shoppingCart.setUpdateTime(Date.from(Instant.now()));
                dao.updateByPrimaryKeySelective(shoppingCart, Column.buyNumber, Column.updateUser, Column.updateTime);
                return shoppingCart;
            }
        }

        DirectMailGoodsShoppingCart shoppingCart = new DirectMailGoodsShoppingCart();
        shoppingCart.setUserId(userId);
        shoppingCart.setGoodsId(dmProduct.getGoodsId());
        shoppingCart.setDirectMailGoodsId(dmProduct.getDirectMailGoodsId());
        shoppingCart.setProductId(dmProduct.getProductId());
        shoppingCart.setDirectMailProductId(directMailProductId);
        shoppingCart.setSpecNames(dmProduct.getSpecNames());
        shoppingCart.setBuyNumber(buyNumber);
        shoppingCart.setCurrencyType(dmGoods.getCurrencyType());
        shoppingCart.setRetailPrice(dmProduct.getRetailPrice());
        shoppingCart.setTotalPrice(dmProduct.getRetailPrice().multiply(BigDecimal.valueOf(buyNumber)));
        shoppingCart.setDeleted(DirectMailGoodsShoppingCart.NOT_DELETED);
        shoppingCart.setStatus(DirectMailGoodsShoppingCartStatus.VALID.real());
        shoppingCart.setIsTemporary(isTemporary);
        shoppingCart.setCreateUser(userName);
        shoppingCart.setCreateTime(Date.from(Instant.now()));
        shoppingCart.setUpdateUser(userName);
        shoppingCart.setUpdateTime(Date.from(Instant.now()));

        // 获取购物车产品名称 直邮产品名称 > 直邮商品名称 > 产品名称 > 商品名称
        if (Check.notNullOrTrimEmpty(dmProduct.getCustomName())) {
            shoppingCart.setName(dmProduct.getCustomName());
        } else if (Check.notNullOrTrimEmpty(dmGoods.getCustomName())) {
            shoppingCart.setName(dmGoods.getCustomName());
        } else if (Check.notNullOrTrimEmpty(product.getName())) {
            shoppingCart.setName(product.getName());
        } else {
            shoppingCart.setName(goods.getName());
        }
        // 获取购物车产品图片 产品图片 > 商品图片
        if (Check.notNullOrTrimEmpty(product.getImage())) {
            shoppingCart.setImage(product.getImage());
        } else {
            shoppingCart.setImage(goods.getImage());
        }

        dao.insert(shoppingCart);
        return shoppingCart;
    }

    public DirectMailGoodsShoppingCart getByDirectMailProductIdAndNotTemporary(Integer userId, Integer directMailProductId) {
        DirectMailGoodsShoppingCartExample example = new DirectMailGoodsShoppingCartExample();
        example.createCriteria().andUserIdEqualTo(userId).andDirectMailProductIdEqualTo(
            directMailProductId).andIsTemporaryEqualTo(false).andDeletedEqualTo(DirectMailGoodsShoppingCart.NOT_DELETED);
        return dao.selectOneByExample(example);
    }

    @Transactional
    public void del(List<Integer> cartIdList, Integer userId, String userName) {
        for (Integer cartId : cartIdList) {
            DirectMailGoodsShoppingCart shoppingCart = getShoppingCartById(cartId, userId);
            BizAssert.isTrue(Check.notNull(shoppingCart), ResultCode.VERIFY.build(10), "购物车商品不存在");
            shoppingCart.setDeleted(DirectMailGoodsShoppingCart.IS_DELETED);
            shoppingCart.setUpdateUser(userName);
            shoppingCart.setUpdateTime(Date.from(Instant.now()));
            dao.updateByPrimaryKeySelective(shoppingCart, Column.deleted, Column.updateTime, Column.updateUser);
        }
    }

    public DirectMailGoodsShoppingCart update(Integer cartId, Integer buyNumber, Integer userId) {
        DirectMailGoodsShoppingCart shoppingCart = getShoppingCartById(cartId, userId);
        BizAssert.isTrue(Check.notNull(shoppingCart), ResultCode.VERIFY.build(10), "购物车商品不存在");
        BizAssert.isTrue(buyNumber > 0 && buyNumber < 100, ResultCode.VERIFY.build(11), "购物车[{}]数量必须小于100", shoppingCart.getName());
        shoppingCart.setBuyNumber(buyNumber);
        shoppingCart.setTotalPrice(shoppingCart.getRetailPrice().multiply(BigDecimal.valueOf(buyNumber)));
        shoppingCart.setUpdateTime(Date.from(Instant.now()));
        dao.updateByPrimaryKeySelective(shoppingCart, Column.buyNumber, Column.totalPrice, Column.updateTime);
        return shoppingCart;
    }

    public DirectMailGoodsShoppingCart getShoppingCartById(Integer cartId, Integer userId) {
        DirectMailGoodsShoppingCartExample example = new DirectMailGoodsShoppingCartExample();
        Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(DirectMailGoodsShoppingCart.NOT_DELETED);
        criteria.andUserIdEqualTo(userId);
        criteria.andCartIdEqualTo(cartId);
        return dao.selectOneByExample(example);
    }

    public List<DirectMailGoodsShoppingCart> queryByCartIds(List<Integer> cartIds, Integer userId) {
        DirectMailGoodsShoppingCartExample example = new DirectMailGoodsShoppingCartExample();
        Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(DirectMailGoodsShoppingCart.NOT_DELETED);
        criteria.andUserIdEqualTo(userId);
        criteria.andCartIdIn(cartIds);
        return dao.selectByExample(example);
    }

    public Pagination<DirectMailGoodsShoppingCart> query(Sorting[] sorts, Page page, Integer userId) {
        DirectMailGoodsShoppingCartExample example = new DirectMailGoodsShoppingCartExample();
        Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(DirectMailGoodsShoppingCart.NOT_DELETED);
        criteria.andStatusEqualTo(DirectMailGoodsShoppingCartStatus.VALID.real());
        criteria.andIsTemporaryEqualTo(false);
        criteria.andUserIdEqualTo(userId);

        example.orderBy(Sortings.builder(sorts).verify(Column::valueOf).toSql());
        example.setOffset(page.getFirstIndex());
        example.setRows(page.getPageSize());
        return Pagination.create(page, dao.countByExample(example), () -> dao.selectByExample(example));
    }

    public Long countValidTotalNumberByUserId(Integer userId) {
        DirectMailGoodsShoppingCartExample example = new DirectMailGoodsShoppingCartExample();
        DirectMailGoodsShoppingCartExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(DirectMailGoodsShoppingCart.NOT_DELETED);
        criteria.andStatusEqualTo(DirectMailGoodsShoppingCartStatus.VALID.real());
        criteria.andUserIdEqualTo(userId);
        criteria.andIsTemporaryEqualTo(false);
        return dao.countByExample(example);
    }

    /**
     * 作废购物车商品
     * 
     * @param directMailProductId
     * @param updateUser
     */
    public void invalidByDirectMailProductId(Integer directMailProductId, String updateUser) {
        DirectMailGoodsShoppingCartExample example = new DirectMailGoodsShoppingCartExample();
        example.createCriteria().andDirectMailProductIdEqualTo(directMailProductId).andStatusEqualTo(
            DirectMailGoodsShoppingCartStatus.VALID.real()).andDeletedEqualTo(DirectMailGoodsShoppingCart.NOT_DELETED);

        DirectMailGoodsShoppingCart record = new DirectMailGoodsShoppingCart();
        record.setStatus(DirectMailGoodsShoppingCartStatus.INVALID.real());
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));

        dao.updateByExampleSelective(record, example, Column.status, Column.updateUser, Column.updateTime);
    }

    public void invalidByProductId(Integer productId, String updateUser) {
        DirectMailGoodsShoppingCartExample example = new DirectMailGoodsShoppingCartExample();
        example.createCriteria().andProductIdEqualTo(productId).andStatusEqualTo(
            DirectMailGoodsShoppingCartStatus.VALID.real()).andDeletedEqualTo(DirectMailGoodsShoppingCart.NOT_DELETED);

        DirectMailGoodsShoppingCart record = new DirectMailGoodsShoppingCart();
        record.setStatus(DirectMailGoodsShoppingCartStatus.INVALID.real());
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));

        dao.updateByExampleSelective(record, example, Column.status, Column.updateUser, Column.updateTime);
    }

    public void invalidByDirectMailGoodsId(Integer directMailGoodsId, String updateUser) {
        DirectMailGoodsShoppingCartExample example = new DirectMailGoodsShoppingCartExample();
        example.createCriteria().andDirectMailGoodsIdEqualTo(directMailGoodsId).andStatusEqualTo(
            DirectMailGoodsShoppingCartStatus.VALID.real()).andDeletedEqualTo(DirectMailGoodsShoppingCart.NOT_DELETED);

        DirectMailGoodsShoppingCart record = new DirectMailGoodsShoppingCart();
        record.setStatus(DirectMailGoodsShoppingCartStatus.INVALID.real());
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));

        dao.updateByExampleSelective(record, example, Column.status, Column.updateUser, Column.updateTime);
    }

    public void updateProductInfo(GoodsProduct product, String updateUser) {
        DirectMailGoodsShoppingCartExample example = new DirectMailGoodsShoppingCartExample();
        example.createCriteria().andProductIdEqualTo(product.getProductId()).andStatusEqualTo(
            DirectMailGoodsShoppingCartStatus.VALID.real()).andDeletedEqualTo(DirectMailGoodsShoppingCart.NOT_DELETED);

        DirectMailGoodsShoppingCart record = new DirectMailGoodsShoppingCart();
        record.setSpecNames(product.getSpecNames());
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));

        dao.updateByExampleSelective(record, example, Column.specNames, Column.updateUser, Column.updateTime);
    }

    public DirectMailGoodsShoppingCart getByIdAndUserId(Integer cartId, Integer userId) {
        DirectMailGoodsShoppingCartExample example = new DirectMailGoodsShoppingCartExample();
        example.createCriteria().andCartIdEqualTo(cartId).andUserIdEqualTo(userId).andDeletedEqualTo(
            DirectMailGoodsShoppingCart.NOT_DELETED);
        return dao.selectOneByExample(example);
    }

    public void delete(DirectMailGoodsShoppingCart cart, String updateUser) {
        cart.setDeleted(DirectMailGoodsShoppingCart.IS_DELETED);
        cart.setUpdateUser(updateUser);
        cart.setUpdateTime(Date.from(Instant.now()));
        dao.updateByPrimaryKeySelective(cart, Column.deleted, Column.updateUser, Column.updateTime);
    }

}